﻿#pragma once
#define LK_COLLECTION_REFERENCEARRAY_
namespace LK
{
	namespace Collection
	{
		template<class T>struct PReferenceArray :PArray<T>
		{
			typedef ReferenceArray<T> vReferenceArray;
			PMETHODS(PReferenceArray<T>, vReferenceArray)
		};
		template<class T>struct ReferenceArray :IArray<T>
		{
			typedef PReferenceArray<T> xReferenceArray;
			BMETHODS(xReferenceArray, ReferenceArray<T>)

				/**
				@brief 指向所引用的数组*/
				T*data;
			/**
			@brief 当前元素数量*/
			index_t Length;
			/**
			@brief 获取元素数*/
			index_t size()const { return Length; }
			/**
			@brief 记录所引用的数组的可用元素数*/
			index_t MaxSize;
			/**
			@brief 获取数组当前最大容量
			@note 当数组元素数不大于最大容量，而且两者之差不大于MaxUnusedLength时，对象存储区域将不会进行内存的重新调整*/
			index_t GetMaxSize()const { return MaxSize; }
			/**
			@brief 长度检查，len为负或越上限都抛出异常*/
			void CheckLength(index_t len)const { if (len<0)throw PInvalidArgumentException(L"标记数组长度不可以为负值"); if (len > MaxSize)throw PIndexOutOfRangeException(L"标记长度超过原数组长度"); }
			/**
			@brief 长度限制，len为负将抛出异常*/
			index_t LimitLength(index_t len)const { if (len < 0)throw PInvalidArgumentException(L"标记数组长度不可以为负值"); return len>MaxSize ? MaxSize : len; }
			/**
			@brief 获取数组内容首地址*/
			virtual void const* GetData()const { return data; }
			/**
			@brief 返回一个浅表副本*/
			ReferenceArray* Clone()const { return new ReferenceArray(*this); }
			/**
			@brief 调整大小，返回调整后数组元素最大大小
			@note 如果len>MaxSize或者len<0都将抛出异常*/
			virtual index_t Resize(index_t len)
			{
				CheckLength(len);
				Length = len;
				return MaxSize;
			}
			/**
			@brief 直接传入元素数和指针来构造直接引用数组
			@param [传入]参数len用以指数组的元素数
			@param [传入]参数p指向已存在的数组
			@note 若len<0将抛出异常，若p为NULL将抛出异常*/
			ReferenceArray(index_t len, const T*p) :data((T*)p), MaxSize(len) { CheckLength(Length = len); if (!p)throw PPointerIsNullException(); }
			/**
			@brief 从C-Style数组引用构造*/
			template<class TT>ReferenceArray(const TT&arr, typename UseIf<IsArray<TT>::V&& IsSame<TT, T>::V>::T*p = NULL) : data((T*)arr), MaxSize(IsArray<TT>::C) { Length = IsArray<TT>::C; }
		};
	}
}
